from PySide6.QtCore import QThread, Signal
from pathlib import Path
import shutil
from contract_renamer.utils.ocr_utils import OCRProcessor
from contract_renamer.config import DOC_TYPES, SUPPORTED_FORMATS

class Worker(QThread):
    progress_updated = Signal(int)
    status_updated = Signal(str)
    finished = Signal()

    def __init__(self, input_dir, output_dir, mode="ocr"):
        super().__init__()
        self.input_dir = input_dir
        self.output_dir = output_dir
        self.mode = mode
        self.should_stop = False
        self.ocr_utils = OCRProcessor()
        
        # 初始化文件列表
        self.files = []
        self._init_file_list()

    def _init_file_list(self):
        """初始化要处理的文件列表"""
        input_path = Path(self.input_dir)
        self.files = [
            str(f) for f in input_path.glob("**/*")
            if f.is_file() and f.suffix.lower() in SUPPORTED_FORMATS
        ]
        self.status_updated.emit(f"找到 {len(self.files)} 个文件待处理")

    def process_file(self, file_path):
        """处理单个文件"""
        if self.should_stop:
            return False

        try:
            if self.mode == "ocr":
                # 显示文件处理分隔符
                self.status_updated.emit("\n" + "=" * 50)
                self.status_updated.emit(f"开始处理文件: {file_path}")
                
                # 首先使用Tesseract
                tesseract_text = self.ocr_utils.tesseract_ocr(file_path)
                tesseract_result = None
                baidu_result = None
                
                if tesseract_text:
                    # 处理Tesseract识别结果
                    doc_type, contract_number, _ = self.ocr_utils.process_text(tesseract_text)
                    tesseract_result = {
                        'text': tesseract_text,
                        'doc_type': doc_type,
                        'contract_number': contract_number
                    }

                # 如果Tesseract无法完全识别，尝试百度OCR
                if not tesseract_text or not (tesseract_result and tesseract_result['doc_type'] and tesseract_result['contract_number']):
                    self.status_updated.emit("\n尝试使用百度OCR识别...")
                    baidu_text, error_msg = self.ocr_utils.baidu_ocr(file_path)
                    
                    if error_msg:
                        self.status_updated.emit(f"百度OCR错误: {error_msg}")
                    
                    if baidu_text:
                        doc_type, contract_number, _ = self.ocr_utils.process_text(baidu_text)
                        baidu_result = {
                            'text': baidu_text,
                            'doc_type': doc_type,
                            'contract_number': contract_number
                        }

                # 使用最佳结果
                if tesseract_result and tesseract_result['doc_type'] and tesseract_result['contract_number']:
                    doc_type = tesseract_result['doc_type']
                    contract_number = tesseract_result['contract_number']
                elif baidu_result and baidu_result['doc_type'] and baidu_result['contract_number']:
                    doc_type = baidu_result['doc_type']
                    contract_number = baidu_result['contract_number']
                else:
                    # 两种方法都失败，使用任一方法识别出的部分信息
                    doc_type = (tesseract_result and tesseract_result['doc_type']) or (baidu_result and baidu_result['doc_type'])
                    contract_number = (tesseract_result and tesseract_result['contract_number']) or (baidu_result and baidu_result['contract_number'])
                    
                    # 只有在识别失败时才显示原始内容
                    self.status_updated.emit("\n无法完全识别文件信息:")
                    if not doc_type and not contract_number:
                        self.status_updated.emit("文档类型和合同号均未识别")
                        if tesseract_result:
                            self.status_updated.emit("\nTesseract识别内容：")
                            self.status_updated.emit(tesseract_result['text'])
                        if baidu_result:
                            self.status_updated.emit("\n百度OCR识别内容：")
                            self.status_updated.emit(baidu_result['text'])
                        return self._move_file(file_path, DOC_TYPES['UNKNOWN'], None)
                    elif not doc_type:
                        self.status_updated.emit("未能识别文档类型")
                        return self._move_file(file_path, DOC_TYPES['UNKNOWN'], contract_number)
                    else:
                        self.status_updated.emit("未能识别合同号")

                # 移动文件
                result = self._move_file(file_path, doc_type, contract_number)
                self.status_updated.emit("=" * 50 + "\n")
                return result

            else:
                # 按文件名分类模式
                doc_type = self._classify_by_filename(file_path)
                contract_number = None
                if doc_type == DOC_TYPES['UNKNOWN']:
                    self.status_updated.emit(f"无法从文件名识别文档类型: {file_path}")

        except Exception as e:
            self.status_updated.emit(f"处理文件出错 {file_path}: {str(e)}")
            self.status_updated.emit("=" * 50 + "\n")
            return False

    def _classify_by_filename(self, file_path):
        """根据文件名分类"""
        filename = Path(file_path).name.lower()
        if "到货" in filename:
            return DOC_TYPES['ARRIVAL']
        elif "验收" in filename:
            return DOC_TYPES['ACCEPTANCE']
        return DOC_TYPES['UNKNOWN']

    def _move_file(self, file_path, doc_type, contract_number=None):
        """移动文件到对应目录"""
        try:
            # 创建目标目录
            output_dir = Path(self.output_dir) / doc_type
            output_dir.mkdir(parents=True, exist_ok=True)

            # 获取原文件信息
            old_path = Path(file_path)
            original_suffix = old_path.suffix

            # 构建新文件名
            if contract_number:
                # 合同号-文档类型.后缀
                new_name = f"{contract_number}-{doc_type}{original_suffix}"
            else:
                # 如果没有合同号，使用原文件名-文档类型.后缀
                base_name = old_path.stem
                new_name = f"{base_name}-{doc_type}{original_suffix}"

            # 检查目标文件是否已存在
            target_path = output_dir / new_name
            if target_path.exists():
                # 如果文件已存在，添加序号
                counter = 1
                while True:
                    new_name = f"{contract_number}-{doc_type}({counter}){original_suffix}"
                    target_path = output_dir / new_name
                    if not target_path.exists():
                        break
                    counter += 1

            # 移动文件
            shutil.copy2(file_path, target_path)
            self.status_updated.emit(f"已处理: {file_path} -> {target_path}")
            return True

        except Exception as e:
            self.status_updated.emit(f"移动文件失败 {file_path}: {str(e)}")
            return False

    def run(self):
        """处理所有文件"""
        total_files = len(self.files)
        processed = 0

        for file_path in self.files:
            if self.should_stop:
                self.status_updated.emit("处理已停止")
                break

            if self.process_file(file_path):
                processed += 1
                progress = int((processed / total_files) * 100)
                self.progress_updated.emit(progress)

        self.finished.emit()